﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using ArgusLib.InteropServices;

namespace ArgusLib.FFmpeg.swscale
{
	public class SwsVector : NativeWrapper<Interop.SwsVectorNative>
	{
		#region Constructors
		public static SwsVector GetSwsVector(int length)
		{
			return Interop.Functions.sws_allocVec(length);
		}

		public static SwsVector GetSwsVector(double coefficient, int length)
		{
			return Interop.Functions.sws_getConstVec(coefficient, length);
		}

		public static SwsVector GetGaussianVector(double variance, double quality)
		{
			variance = Math.Min(variance, 3);
			variance = Math.Max(variance, 0);
			return Interop.Functions.sws_getGaussianVec(variance, quality);
		}

		public static SwsVector GetIdentityVector()
		{
			return Interop.Functions.sws_getIdentityVec();
		}
		#endregion

		#region Properties
		/// <summary>
		/// Number of coefficients in the vector
		/// </summary>
		public int Length { get { return this.Structure.length; } }

		/// <summary>
		/// List of coefficients
		/// </summary>
		public double[] Coefficients
		{
			get
			{
				double[] RetVal = new double[this.Structure.length];
				Marshal.Copy(this.Structure.coeff, RetVal, 0, this.Structure.length);
				return RetVal;
			}
		}

		public double this[int index]
		{
			get
			{
				if (index < 0 || index >= this.Structure.length)
					throw new ArgumentOutOfRangeException("index");
				IntPtr ptr = new IntPtr(this.Structure.coeff.ToInt64() + index * Marshal.SizeOf(typeof(double)));
				return (double)Marshal.PtrToStructure(ptr, typeof(double));
			}
			set
			{
				if (index < 0 || index >= this.Structure.length)
					throw new ArgumentOutOfRangeException("index");
				IntPtr ptr = new IntPtr(this.Structure.coeff.ToInt64() + index * Marshal.SizeOf(typeof(double)));
				Marshal.StructureToPtr(value, ptr, false);
			}
		}
		#endregion

		#region Methods
		public SwsVector Clone()
		{
			return Interop.Functions.sws_cloneVec(this);
		}

		public void Normalize(double height)
		{
			Interop.Functions.sws_normalizeVec(this, height);
		}

		public void Scale(double scalar)
		{
			Interop.Functions.sws_scaleVec(this, scalar);
		}

		protected override void DisposeCore()
		{
			Interop.Functions.sws_freeVec(this);
		}
		#endregion
	}
}
